﻿/*

The MIT License

Copyright (c) 2010 Cartesian Analytics, Inc. 

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

*/

using System;

namespace Pipra.Math.Geometry
{
    /// <summary>
    /// A 2D axis aligned minimum bounding rectangle, sometimes known as an envelope.
    /// </summary>
    /// <typeparam name="TValue">The element type.</typeparam>
    public interface IMbr<TValue> :
        IPlanarGeometry<TValue>,
        IHasArea<TValue>,
        IHasDistance<TValue,IMbr<TValue>>,
        IIntersectable<IMbr<TValue>>,
        ITouches<IMbr<TValue>>,
        IOverlappable<IMbr<TValue>>,
        ICanBeDisjoint<IMbr<TValue>>,
        ICanContain<IMbr<TValue>>,
        ICanCross<IMbr<TValue>>,
        IEquatable<IMbr<TValue>>
    {
        /// <summary>
        /// The minimum encompassed value on the x-axis. 
        /// </summary>
        TValue XMin { get; }
        /// <summary>
        /// The maximum encompassed value on the x-axis. 
        /// </summary>
        TValue XMax { get; }
        /// <summary>
        /// The minimum encompassed value on the y-axis. 
        /// </summary>
        TValue YMin { get; }
        /// <summary>
        /// The maximum encompassed value on the y-axis. 
        /// </summary>
        TValue YMax { get; }
        /// <summary>
        /// The minimum coordiante of this MBR.
        /// </summary>
        IPoint2<TValue> Min { get; }
        /// <summary>
        /// The maximum coordiante of this MBR.
        /// </summary>
        IPoint2<TValue> Max { get; }

        /// <summary>
        /// The width of the MBR.
        /// </summary>
        TValue Width { get; }
        /// <summary>
        /// The height of the MBR.
        /// </summary>
        TValue Height { get; }
        /// <summary>
        /// Creates a MBR encompassing this MBR and the given <paramref name="x"/>- and <paramref name="y"/>-coordinate.
        /// </summary>
        /// <param name="x">A x-coordinate.</param>
        /// <param name="y">A y-coordinate.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> Union(TValue x, TValue y);
        /// <summary>
        /// Creates a MBR encompassing this MBR and the given <paramref name="x"/>- and <paramref name="y"/>-coordinates.
        /// </summary>
        /// <param name="x">A x-coordinate range.</param>
        /// <param name="y">A y-coordinate range.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> Union(IRange<TValue> x, IRange<TValue> y);
        /// <summary>
        /// Creates a MBR encompassing this MBR and the given point, <paramref name="p"/>.
        /// </summary>
        /// <param name="p">A point.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> Union(ICoordinatePair<TValue> p);
        /// <summary>
        /// Creates a MBR encompassing this MBR and the given points, <paramref name="a"/> and <paramref name="b"/>.
        /// </summary>
        /// <param name="a">A point.</param>
        /// <param name="b">A point.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> Union(ICoordinatePair<TValue> a, ICoordinatePair<TValue> b);
        /// <summary>
        /// Creates a MBR encompasing this MBR and the given <paramref name="mbr"/>.
        /// </summary>
        /// <param name="mbr">A MBR.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> Union(IMbr<TValue> mbr);
        /// <summary>
        /// Gets a copy of the MBR at the same center point but a scaled width and height.
        /// </summary>
        /// <param name="scale">The scaling factor for the width and height.</param>
        /// <returns>A Mbr.</returns>
        IMbr<TValue> GetScaled(TValue scale);
        /// <summary>
        /// Gets a copy of the MBR at the same center point but with the given dimensions.
        /// </summary>
        /// <param name="size">The dimensions.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> GetResized(IVector2<TValue> size);
        /// <summary>
        /// Gets a copy of the MBR at the given <paramref name="center"/> point but with the same dimensions.
        /// </summary>
        /// <param name="center">The center point.</param>
        /// <returns>A MBR.</returns>
        IMbr<TValue> GetCentered(ICoordinatePair<TValue> center);

    }
}
